/*
 * monster.c
 *
 *  Created on: 10 mai 2013
 *      Author: User One
 */


#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include <SDL.h>
#include <SDL_image.h>

#include "../include/game.h"
#include "../include/misc.h"
#include "../include/map.h"
#include "../include/monster.h"

struct s_monster {
	int x, y;
	SDL_Surface * directed_img[4];
	enum e_way current_way;
	Uint32 time;
	int alive;

	int tmp[4];

	int nb_life;
};

// Creates a new monster with a given number of available bombs and lives
t_monster monster_init(int life_number) {
	t_monster monster = malloc(sizeof(*monster));
	if (!monster)
		error("Memory error");

	monster->directed_img[WEST] = load_image(IMG_MONSTER_LEFT);
	monster->directed_img[EAST] = load_image(IMG_MONSTER_RIGHT);
	monster->directed_img[NORTH] = load_image(IMG_MONSTER_UP);
	monster->directed_img[SOUTH] = load_image(IMG_MONSTER_DOWN);

	monster->current_way = SOUTH;
	monster->nb_life = life_number;
	monster->time = SDL_GetTicks();
	monster->alive = 1;
	monster->x = 13;
	monster->y = 13;

	return monster;
}

void monster_free(t_monster monster) {
	assert(monster);
	int i;
	for (i = 0; i < 4; i++)
		SDL_FreeSurface(monster->directed_img[i]);

	free(monster);
}

int monster_get_x(t_monster monster) {
	assert(monster != NULL);
	return monster->x;
}

int monster_get_y(t_monster monster) {
	assert(monster != NULL);
	return monster->y;
}

// sets the position of the monster
void monster_set_xy(t_monster monster, int x, int y) {
	assert(monster != NULL);
	monster->x = x;
	monster->y = y;

}

// Returns the time of the monster
Uint32 monster_get_time(t_monster monster) {
	assert(monster != NULL);
		return monster->time;
}

// Returns whether the monster is alive
int monster_get_stat(t_monster monster){
	assert(monster != NULL);
	return monster->alive;
}

// Resets the time of the monster
void monster_reset_time(t_monster monster) {
	assert(monster != NULL);
	monster->time = SDL_GetTicks();
}

// Set the direction of the next move of the monster
void monster_set_current_way(t_monster monster, enum e_way way) {
	assert(monster);
	monster->current_way = way;
}

// Loads the monsters positions from the map
void monster_from_map(t_monster* monster, t_map map) {
	int i, j;
	int k=0;
	monster_reset_time(*monster);
	for (i = 0; i < map_get_width(map); i++) {
		for (j = 0; j < map_get_height(map); j++) {
			if (map_get_cell_type(map, i, j) == CELL_MONSTER ) {
				monster[k]->x = i;
				monster[k]->y = j;
				k++;

			}
		}
	}
}

// Selects a random direction for the monster
void select_random_direction(t_monster monster, int j){
	int randNum=0,i=0;
	srand(time(NULL));

	for (i=0;i<100;i++){
		randNum = 4 * (rand() / (RAND_MAX + 1.0)) + j;
	}

	if (monster_get_stat(monster)){
		switch (randNum){
		case 0:
			monster_set_current_way(monster,NORTH);
			break;
		case 1:
			monster_set_current_way(monster,SOUTH);
			break;
		case 2:
			monster_set_current_way(monster,EAST);
			break;
		case 3:
			monster_set_current_way(monster,WEST);
			break;
		case 4:
			monster_set_current_way(monster,EAST);
			break;
		case 5:
			monster_set_current_way(monster,NORTH);
			break;
		case 6:
			monster_set_current_way(monster,WEST);
			break;
		case 7:
			monster_set_current_way(monster,SOUTH);
			break;

		default :
			monster_set_current_way(monster,SOUTH);
			break;
		}

	}
}

// Checks whether the monster is in the reach of an exploding bomb
int bomb_explods_monster(t_monster monster, t_map map, t_player player){
	int x = monster_get_x(monster);
	int y = monster_get_y(monster);
	int rang = player_get_rang(player);
	int ji = 1;
	while ( ji <= rang){

		if (	(map_is_inside(map,x+ji,y) && map_get_cell_type(map, x+ji, y) == CELL_BOMB )||
				(map_is_inside(map,x,y+ji) && map_get_cell_type(map, x, y+ji) == CELL_BOMB )||
				(map_is_inside(map,x-ji,y) && map_get_cell_type(map, x-ji, y) == CELL_BOMB )||
				(map_is_inside(map,x,y-ji) && map_get_cell_type(map, x, y-ji) == CELL_BOMB )||
				(map_is_inside(map,x,y) && map_get_cell_type(map, x, y) == CELL_BOMB )
		){
			return 1;
		}
		ji++;
	}

	return 0;
}


void monster_die (t_monster monster, t_map map) {
	int x = monster_get_x(monster);
	int y = monster_get_y(monster);
	monster->alive = 0; // the alive parameter is set to 0,
	map_set_cell_type(map, x, y, CELL_EMPTY); // and the cell to CELL_EMPTY
}

static int monster_move_aux(t_monster monster, t_map map, t_player player, int x1, int y1, int x2,
		int y2) {

	if (!map_is_inside(map, x1, y1))
		return 0;

	switch (map_get_cell_type(map, x1, y1)) {
	case CELL_SCENERY:
		return 0; // can't move
		break;

	case CELL_CASE:
		return 0;// can't move
		break;

	case CELL_BOMB:
		return 0;// can't move
		break;

	case CELL_BONUS:
		return 0;// can't move
		break;

	case CELL_GOAL:
		return 0;// can't move
		break;

	case CELL_MONSTER:
		return 0;// can't move
		break;

	case CELL_PLAYER:// if a monster walks on the player, the players loses a life
		if (player_get_nb_life(player)>-1){
		player_dec_nb_life(player);
		}
		return 0;// can't move
		break;

	case CELL_KEY:
		return 0;// can't move
		break;

	case CELL_DOOR:
		return 0;// can't move
		break;

	case CELL_CLOSED_DOOR :
		return 0;// can't move
		break;

	default:
		break;
	}

	// monster has moved
	return 1;
}

// Move the monster according to the current direction
int monster_move(t_monster monster, t_map map, t_player player) {
	int x = monster->x;
	int y = monster->y;
	int move = 0;

	switch (monster->current_way) {
	case NORTH:
		if (monster_move_aux(monster, map, player, x, y - 1, x, y - 2) ) {
			monster->y--;
			move = 1;
		}
		break;

	case SOUTH:
		if (monster_move_aux(monster, map, player, x, y + 1, x, y + 2) ) {
			monster->y++;
			move = 1;
		}
		break;

	case WEST:
		if (monster_move_aux(monster, map, player, x - 1, y, x - 2, y)) {
			monster->x--;
			move = 1;
		}
		break;

	case EAST:
		if (monster_move_aux(monster, map, player, x + 1, y, x + 2, y) ) {
			monster->x++;
			move = 1;
		}
		break;
	}

	if (move) {
		map_set_cell_type(map, x, y, CELL_EMPTY);
		map_set_cell_type(map, monster->x, monster->y, CELL_MONSTER);
	}
	return move;
}

void monster_disppear(t_monster monster){ // Takes the monster outside of the map, he can't move anymore
											// So can't get back in
	monster->x = 14;
	monster->y = 14;
}

void monster_display(t_monster monster, SDL_Surface *screen) {
	assert(monster);
	assert(monster->directed_img[monster->current_way]);
	assert(screen);

	SDL_Rect place;
	place.x = monster->x * SIZE_BLOC;
	place.y = monster->y * SIZE_BLOC;

	SDL_BlitSurface(monster->directed_img[monster->current_way], NULL, screen,
			&place);

}

